/**
 * 
 */
package com.imonsoft.common.util;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

/**
 * 图片处理基础类
 * 
 * @author LiQianHui
 * @date 2013-04-17
 * @version 2013
 */
public abstract class ImageUtil {

	protected final static Log logger = LogFactory.getLog(ImageUtil.class);

	/**
	 * 图片缩放
	 * 
	 * @param file
	 * @param outputWidth
	 * @param outputHeight
	 * @return
	 * @throws IOException
	 */
	public static BufferedImage zoom(File file, int outputWidth,
			int outputHeight) throws IOException {
		BufferedImage srcImage = ImageIO.read(file);
		// 构造一个预定义的图像类型的BufferedImage对象
		BufferedImage buffImg = new BufferedImage(outputWidth, outputHeight,
				BufferedImage.TYPE_INT_RGB);
		// 创建Graphics2D对象，用于在BufferedImage对象上绘图
		Graphics2D g2d = buffImg.createGraphics();
		g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
				RenderingHints.VALUE_FRACTIONALMETRICS_ON);
		g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
				RenderingHints.VALUE_RENDER_QUALITY);
		// 设置图形上下文的当前颜色为白色
		g2d.setColor(Color.WHITE);
		g2d.fillRect(0, 0, outputWidth, outputHeight);
		// 按照缩放的大小在BufferedImage对象上绘制原始图像
		g2d.drawImage(srcImage, 0, 0, outputWidth, outputHeight, null);
		// 释放图形上下文使用的系统资源的。
		g2d.dispose();
		return buffImg;
	}

	public static File createPreviewImage(BufferedImage bis, File destFile,
			int outputWidth, int outputHeight) {
		try {
			int w = bis.getWidth();
			int h = bis.getHeight();
			// 在图像不变形的情况下，最大限度的使转换接近outputWidth,outputHeight
			int nw = outputWidth;
			int nh = (nw * h) / w; // 根据outputWidth算nh
			if (nh > outputHeight) {
				nh = outputHeight;
				nw = (nh * w) / h;// 根据outputHeight算nw
			}
			double sx = (double) nw / w;
			double sy = (double) nh / h;

			AffineTransformOp ato = new AffineTransformOp(AffineTransform
					.getScaleInstance(sx, sy), null);
			BufferedImage bid = new BufferedImage(nw, nh,
					BufferedImage.TYPE_3BYTE_BGR);
			ato.filter(bis, bid);
			ImageIO.write(bid, "jpeg", destFile);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(
					" Failed in create preview image. Error:  "
							+ e.getMessage());
		}
		return destFile;
	}

	public static File createPreviewImage(InputStream is, File destFile,
			int outputWidth, int outputHeight) {
		BufferedImage bis = null;
		try {
			bis = ImageIO.read(is);
			createPreviewImage(bis, destFile, outputWidth, outputHeight);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(
					" Failed in create preview image. Error:  "
							+ e.getMessage());
		}
		return destFile;
	}

	public static File createPreviewImage(File srcFile, File destFile,
			int outputWidth, int outputHeight) {
		try {
			BufferedImage bis = ImageIO.read(srcFile);
			createPreviewImage(bis, destFile, outputWidth, outputHeight);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(
					" Failed in create preview image. Error:  "
							+ e.getMessage());
		}
		return destFile;
	}

	public static void createPreviewImage(InputStream is, String destFile,
			int outputWidth, int outputHeight) {
		BufferedImage bis = null;
		try {
			bis = ImageIO.read(is);
			createPreviewImage(bis, new File(destFile), outputWidth,
					outputHeight);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(
					" Failed in create preview image. Error:  "
							+ e.getMessage());
		}
	}

	public static void createPreviewImage(File srcFile, String destFile,
			int outputWidth, int outputHeight) {
		createPreviewImage(srcFile, new File(destFile), outputWidth,
				outputHeight);
	}

	/**
	 * 压缩图片
	 * 
	 * @param srcFile
	 *            原文件路径
	 * @param destFile
	 *            转换后的路径
	 * @param outputWidth
	 *            宽
	 * @param outputHeight
	 *            高
	 */
	public static void createPreviewImage(String srcFile, String destFile,
			int outputWidth, int outputHeight) {
		createPreviewImage(new File(srcFile), new File(destFile), outputWidth,
				outputHeight);
	}

	/**
	 * 文字图片
	 * 
	 * @param str
	 *            传入要转换图片的文字
	 * @return
	 */
	public static BufferedImage str2image(String str) {
		int width = 100;
		int height = 20;
		BufferedImage bufferedImage = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = bufferedImage.createGraphics();
		g2.setColor(Color.WHITE);
		g2.fillRect(0, 0, width, height);
		g2.setColor(Color.BLACK);
		g2.drawString(str, 0, height - 2);
		g2.dispose();
		return bufferedImage;
	}

	/**
	 * 潮汛网压缩图片
	 * @param originalFile 原图路径
	 * @param resizedFile 压缩图片路径
	 * @param newWidth 压缩后的宽度
	 * @param quality  压缩比例 亮度比例
	 * @param isHeight 是否需要考虑压缩高度 true则考虑
	 * @throws IOException
	 */
	public static void imageResize(String originalFile, String resizedFile,
			int newWidth) throws IOException {
		resize(originalFile, resizedFile, newWidth, (float) 1, false);
	}

	/**
	 * 
	 * @param originalFile 原图路径
	 * @param resizedFile 压缩图片路径
	 * @param newWidth 压缩后的宽度
	 * @param quality  压缩比例 亮度比例
	 * @param isHeight 是否需要考虑压缩高度 true则考虑
	 * @throws IOException
	 */
	public static void resize(String originalFile, String resizedFile,
			int newWidth, float quality, boolean isHeight) throws IOException {
		if (quality < 0 || quality > 1) {
			throw new IllegalArgumentException(
					"Quality has to be between 0 and 1");
		}
		ImageIcon ii = new ImageIcon(originalFile);
		Image i = ii.getImage();
		Image resizedImage = null;
		int iWidth = i.getWidth(null);
		int iHeight = i.getHeight(null);
		/**
		 * 是否需要压缩高度
		 */
		if (isHeight) {
			if (iWidth > iHeight) {
				resizedImage = i.getScaledInstance(newWidth,
						(newWidth * iHeight) / iWidth, Image.SCALE_SMOOTH);
			} else {
				resizedImage = i.getScaledInstance((newWidth * iWidth)
						/ iHeight, newWidth, Image.SCALE_SMOOTH);
			}
		} else {
			/**
			 * 宽度等比例压缩
			 */
			resizedImage = i.getScaledInstance(newWidth, (newWidth * iHeight)
					/ iWidth, Image.SCALE_SMOOTH);
		}

		// This code ensures that all the pixels in the image are loaded.
		Image temp = new ImageIcon(resizedImage).getImage();

		// Create the buffered image.
		BufferedImage bufferedImage = new BufferedImage(temp.getWidth(null),
				temp.getHeight(null), BufferedImage.TYPE_INT_RGB);

		// Copy image to buffered image.
		Graphics g = bufferedImage.createGraphics();

		// Clear background and paint the image.
		g.setColor(Color.white);
		g.fillRect(0, 0, temp.getWidth(null), temp.getHeight(null));
		g.drawImage(temp, 0, 0, null);
		g.dispose();

		// Soften.
		float softenFactor = 0.00f;
		float[] softenArray = { 0, softenFactor, 0, softenFactor,
				1 - (softenFactor * 4), softenFactor, 0, softenFactor, 0 };
		Kernel kernel = new Kernel(3, 3, softenArray);
		ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
		bufferedImage = cOp.filter(bufferedImage, null);

		// Write the jpeg to a file.
		FileOutputStream out = new FileOutputStream(resizedFile);

		// Encodes image as a JPEG data stream
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		JPEGEncodeParam param = encoder
				.getDefaultJPEGEncodeParam(bufferedImage);
		param.setQuality(quality, true);
		encoder.setJPEGEncodeParam(param);
		encoder.encode(bufferedImage);
		out.close();
	}

	public static void main(String[] args) {
		// createPreviewImage("d:/22.jpg", "d:/mini.jpg", 350, 530);
		// createPreviewImage(str2image("430124198008155625"), new File(
		// "d:/str2image.jpg"), 100, 125);
		try {
			imageResize("d:/27pmu_kqyvq43ckrbguwsugfjeg5sckzsew_500x750.jpg_320x999.jpg","d:/test.jpg", 200);
			// File file = new File("d:/mini.jpg");
			// BufferedImage bi = zoom(new File("d:/22.jpg"), 100, 100);
			// ImageIO.write(bi, "JPG ", file);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
